//
//	MiscPriorityQueue.m -- a Priority Queue
//		Written by Doug McClure Copyright (c) 1994 by Doug McClure.
//				Version 1.0.  All rights reserved.
//
//		This notice may not be removed from this source code.
//
//	This object is included in the MiscKit by permission from the author
//	and its use is governed by the MiscKit license, found in the file
//	"LICENSE.rtf" in the MiscKit distribution.  Please refer to that file
//	for a list of all applicable permissions and restrictions.
//	

/*
 * $RCSfile$
 *
 * $Author$
 *
 * $Revision$
 *
 * $Date$
 *
*/

#import <misckit/MiscPriorityQueue.h>

#define MiscPriorityQueueVersion	100

typedef struct _Node
{
  unsigned priority;
  id object;
}
Node;

@implementation MiscPriorityQueue

- dequeue
{
  Node *node;
  
  if ( [self count] )
    {
      node = ((Node *)[self lastElement]);
      [self removeLastElement];
      return node->object;
    }
  
  return nil;
}


- enqueue:anObject withPriority:(int)priority
{
  Node *newNode;
  
  newNode = (Node *)NXZoneMalloc([self zone], sizeof(Node));
  newNode->priority = priority;
  newNode->object = anObject;

  return [self addElement:newNode];
}


- init
{
  return [self initCount:0];
}


- initCount:(unsigned int)numSlots
{
  return [self initCount:numSlots elementSize:sizeof(Node) description:@encode(Node)];
}


- (BOOL)isEqual:anObject
{
  return NO;
}


- (unsigned)highestPriority
{
  return [self priorityAt:([self count]-1)];
}


- (unsigned)lowestPriority
{
  return [self priorityAt:0];
}


- makeObjectsPerform:(SEL)aSelector
{
  Node *node;

  for ( node = ((Node *)[self setFirstElement]) ; (id)node != nil ; node = ((Node *)[self setNextElement]) )
    {
      if ( [node->object respondsTo:aSelector] )
	{
	  [node->object perform:aSelector];
	}
    }
  
  return self;
}


- makeObjectsPerform:(SEL)aSelector with:anObject
{
  Node *node;

  for ( node = ((Node *)[self setFirstElement]) ; (id)node != nil ; node = ((Node *)[self setNextElement]) )
    {
      if ( [node->object respondsTo:aSelector] )
	{
	  [node->object perform:aSelector with:anObject];
	}
    }
  
  return self;
}


- objectAt:(unsigned)index
{
  Node *node;
  
  if ( index < [self count] )
    {
      node = ((Node*)[self elementAt:index]);
      return node->object;
    }
  
  return nil;
}

  
- (unsigned)priorityAt:(unsigned)index
{
  Node *node;
  
  if ( index < [self count] )
    {
      node = ((Node*)[self elementAt:index]);
      return node->priority;
    }
  
  return NX_NOT_IN_LIST;
}


- read:(NXTypedStream *)stream
{
  return self;
}


- write:(NXTypedStream *)stream
{
  return self;
}

@end


@implementation MiscPriorityQueue(OverrideMethods)

- (int)compare:(void *)elementA to:(void *)elementB caseCheck:(BOOL)flag
{
  Node *nodeA = ((Node *)elementA);
  Node *nodeB = ((Node *)elementB);

  if ( nodeA->priority < nodeB->priority )
    {
      return -1;
    }
  else if ( nodeA->priority > nodeB->priority )
    {
      return 1;
    }
  else
    {
      return 0;
    }
}

@end
